package com.db.stexchem.client.gui;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.net.UnknownHostException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import com.db.stexchem.client.Client;
import com.db.stexchem.exceptions.BadRequestException;

public class LoginPanel extends JPanel {
  private boolean                hostEntered      = false;
  private boolean                portEntered      = false;
  private boolean                loginEntered     = false;
  private boolean                passwordEntered  = false;

  private JTextField             hostTextField    = new JTextField();
  private IntegerNumberTextField portTextField    = new IntegerNumberTextField();

  private JTextField             loginTextField   = new JTextField();
  private JPasswordField         passwordField    = new JPasswordField();

  private JButton                connectButton    = new JButton("Connect");
  private JButton                disconnectButton = new JButton("Disonnect");

  private transient Client       application      = null;

  private GridBagConstraints     constraints      = new GridBagConstraints();

  public LoginPanel(final Client application) {
    setName("LoginEntryPanel");
    this.application = application;

    ConnectActivator activator = new ConnectActivator();
    hostTextField.addKeyListener(activator);
    portTextField.addKeyListener(activator);
    loginTextField.addKeyListener(activator);
    passwordField.addKeyListener(activator);

    setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
    setLayout(new GridBagLayout());
    createComponents();
  }

  public void addActionListener(ActionListener listener) {
    connectButton.addActionListener(listener);
  }

  private void createComponents() {
    constraints.fill = GridBagConstraints.BOTH;
    constraints.weightx = 1;

    int x = 0;
    int y = 0;

    add(new JLabel("host"), x, y);
    add(new JLabel("port"), ++x, y);
    add(new JLabel("login"), ++x, y);
    add(new JLabel("password"), ++x, y);

    hostTextField.setName("hostTextField");
    add(hostTextField, x = 0, ++y);
    constraints.ipadx = 0;
    portTextField.setName("portTextField");
    add(portTextField, ++x, y);
    loginTextField.setName("loginTextField");
    add(loginTextField, ++x, y);
    passwordField.setName("passwordField");
    add(passwordField, ++x, y);

    constraints.insets = new Insets(3, 0, 0, 0);
    constraints.gridwidth = GridBagConstraints.RELATIVE;

    constraints.gridwidth = GridBagConstraints.REMAINDER;
    connectButton.setName("connectButton");
    add(connectButton, x, ++y);

    add(disconnectButton, x, ++y);

    disconnectButton.addActionListener(new DisconnectListener());

    connectButton.setEnabled(false);
    connectButton.addActionListener(new ConnectListener());
    activateConnect();
  }

  private JComponent add(JComponent component, int x, int y) {
    constraints.gridx = x;
    constraints.gridy = y;
    add(component, constraints);
    return component;
  }

  private class DisconnectListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      try {
        application.close();
      } catch (IOException e1) { // don't care
      }
    }
  }

  private void activateConnect() {
    connectButton.setEnabled(hostEntered && portEntered && loginEntered
        && passwordEntered);
  }

  private class ConnectListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
      String host = hostTextField.getText();
      int port = Integer.valueOf(portTextField.getText());
      String login = loginTextField.getText();
      String password = new String(passwordField.getPassword());

      try {
        application.connect(host, port, login, password);
      } catch (UnknownHostException e1) {
        JOptionPane.showMessageDialog(LoginPanel.this, "Unknown host: " +
            e1.getMessage(), "Connect error", JOptionPane.ERROR_MESSAGE);
        return;
      } catch (IllegalStateException | IllegalArgumentException | IOException
          | BadRequestException e1) {
        JOptionPane.showMessageDialog(LoginPanel.this, e1.getMessage(),
            "Connect error", JOptionPane.ERROR_MESSAGE);
        return;
      }
    }
  }

  private class ConnectActivator implements KeyListener, ItemListener {
    public void keyReleased(KeyEvent e) {
      Object obj = e.getSource();
      if (obj == hostTextField) {
        hostEntered = testField(obj);
      } else if (obj == portTextField) {
        portEntered = testField(obj);
      } else if (obj == loginTextField) {
        loginEntered = testField(obj);
      } else if (obj == passwordField) {
        passwordEntered = testField(obj);
      }
      activateConnect();
    }

    public void itemStateChanged(ItemEvent e) {
      activateConnect();
    }

    private boolean testField(Object o) {
      String value = ((JTextField) o).getText();
      value = value.trim();
      return value.length() > 0;
    }

    public void keyTyped(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
    }
  }
}
